package pl.us.ij.plugins.segmentation.commands.edges;

import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import pl.us.ij.plugins.segmentation.commands.ArrayHelper;
import pl.us.ij.plugins.segmentation.commands.MatrixHelper;
import pl.us.ij.plugins.segmentation.infrastructure.Command;
import pl.us.ij.plugins.segmentation.infrastructure.exceptions.BreakCommandException;

import static pl.us.ij.plugins.segmentation.commands.ArrayHelper.max;

/**
 * Created by IntelliJ IDEA.
 * User: Przemek
 * Date: 2010-02-28
 * Time: 01:10:24
 * To change this template use File | Settings | File Templates.
 */
public class DilatationCommand extends Command<DilatationCommandParams> {
    @Override
    protected void processImage(FloatProcessor fp) throws BreakCommandException {

        int maskSize = getParams().getMaskSize();
        float[][] mask = MatrixHelper.floatOnes(3);

        int width = fp.getWidth();
        int height = fp.getHeight();

        ImageProcessor ip = fp;

        float[] pixels = (float[]) ip.getPixelsCopy();
        float[] outPixels = (float[]) ip.getPixels();

        final float min = ArrayHelper.min(pixels);
        final float max = ArrayHelper.max(pixels);
        dilatation(width, height, maskSize, pixels, outPixels);

        for (int i = 0; i < pixels.length; i++) {

            float pixel = pixels[i];
            float oPixel = outPixels[i];
            float dPixel = 0;

            if (pixel != oPixel) {
                dPixel = pixel - oPixel;

                if (dPixel < min)
                    dPixel = min;
                if (dPixel > max)
                    dPixel = max;
            }
            outPixels[i] = dPixel;
        }

        ip.setPixels(outPixels);
//        getImageProcessor().setPixels(0, (FloatProcessor) ip);
    }

    public static void dilatation(int width, int height, int maskSize, float[] pixels, float[] outPixels) {
        int[] shifts = new int[maskSize];
        int shiftD = 0;

        final float maxPixel = max(outPixels);

        for (int y = 0; y < height; y++) {

            for (int k = 0; k < maskSize; k++) {
                shifts[k] = (y + (k - maskSize / 2)) * width;
                if (shifts[k] < 0)
                    shifts[k] = 0;
                else if (shifts[k] > (height - 1) * width)
                    shifts[k] = (height - 1) * width;
            }

            shiftD = y * width;

            for (int x = 0; x < width - maskSize / 2; x++) {
                float min = maxPixel;

                for (int yMask = 0; yMask < maskSize; yMask++) {
                    for (int xMask = 0; xMask < maskSize; xMask++) {
                        int q = x + xMask - maskSize / 2;
                        if (q > 0 && q < width && min > pixels[shifts[yMask] + q])
                            min = pixels[shifts[yMask] + q];
                    }
                    outPixels[shiftD + x + (maskSize / 2 - 1)] = min;
                }
            }
        }
    }
}
